# ============================================================================
# 大规模非线性GPU性能测试 - PlasticDamageConcrete3d (2500单元)
# ============================================================================

wipe
puts "=========================================="
puts "大规模非线性混凝土GPU性能测试"
puts "网格规模: 50x50 = 2500 Quad单元"
puts "材料: PlasticDamageConcrete3d (C30混凝土)"
puts "=========================================="

model basic -ndm 2 -ndf 2

# ============================================================================
# 网格参数
# ============================================================================

set nx 50;  # X方向单元数
set ny 50;  # Y方向单元数
set Lx 10.0;  # X方向总长度 (m)
set Ly 10.0;  # Y方向总长度 (m)

set dx [expr $Lx / $nx];  # X方向单元尺寸
set dy [expr $Ly / $ny];  # Y方向单元尺寸

puts "网格尺寸: ${Lx}m x ${Ly}m"
puts "单元尺寸: ${dx}m x ${dy}m"

# ============================================================================
# 塑性损伤混凝土材料 (C30混凝土)
# ============================================================================

# C30混凝土参数:
# E  = 30 GPa (弹性模量)
# nu = 0.2 (泊松比)
# ft = 3 MPa (抗拉强度)
# fc = 30 MPa (抗压强度)
# beta = 0.6 (塑性流动参数)
# Ap = 0.5 (拉伸损伤参数)
# An = 2.0 (压缩损伤参数)
# Bn = 0.75 (压缩损伤指数)

nDMaterial PlasticDamageConcrete3d 1 30.0e9 0.2 3.0e6 30.0e6 0.6 0.5 2.0 0.75

puts "材料定义: PlasticDamageConcrete3d"
puts "  E=30 GPa, nu=0.2, ft=3 MPa, fc=30 MPa"

# ============================================================================
# 创建节点
# ============================================================================

puts "\n创建节点..."
set nodeTag 1

for {set j 0} {$j <= $ny} {incr j} {
    for {set i 0} {$i <= $nx} {incr i} {
        set x [expr $i * $dx]
        set y [expr $j * $dy]
        node $nodeTag $x $y
        incr nodeTag
    }
}

set numNodes [expr ($nx+1) * ($ny+1)]
puts "总节点数: $numNodes"

# ============================================================================
# 创建Quad单元
# ============================================================================

puts "创建Quad单元..."
set thickness 0.2
set eleTag 1

for {set j 0} {$j < $ny} {incr j} {
    for {set i 0} {$i < $nx} {incr i} {
        set n1 [expr $j * ($nx+1) + $i + 1]
        set n2 [expr $n1 + 1]
        set n3 [expr $n1 + ($nx+1) + 1]
        set n4 [expr $n1 + ($nx+1)]

        element quad $eleTag $n1 $n2 $n3 $n4 $thickness "PlaneStress" 1
        incr eleTag
    }
}

set numElements [expr $nx * $ny]
puts "总单元数: $numElements"
puts "单元厚度: ${thickness}m"

# ============================================================================
# 边界条件
# ============================================================================

puts "施加边界条件..."

# 底部节点 (y=0) 完全固定
for {set i 1} {$i <= [expr $nx+1]} {incr i} {
    fix $i 1 1
}

# 左右侧边界: X方向固定，Y方向自由 (防止侧向变形)
for {set j 1} {$j < $ny} {incr j} {
    set leftNode [expr $j * ($nx+1) + 1]
    set rightNode [expr $leftNode + $nx]
    fix $leftNode 1 0
    fix $rightNode 1 0
}

# 顶部节点: X方向固定，Y方向自由
set topRowStart [expr $ny * ($nx+1) + 1]
for {set i 0} {$i <= $nx} {incr i} {
    set nodeId [expr $topRowStart + $i]
    fix $nodeId 1 0
}

puts "边界条件: 底部固定，侧边X固定，顶部Y自由"

# ============================================================================
# 均布载荷 (施加在顶部节点)
# ============================================================================

puts "施加均布载荷..."

# 总载荷 = 100 kN (压缩)
# 每个顶部节点载荷 = 100 kN / (nx+1)
set totalLoad -100.0e3
set nodeLoad [expr $totalLoad / ($nx + 1)]

pattern Plain 1 Linear {
    for {set i 0} {$i <= $nx} {incr i} {
        set nodeId [expr $topRowStart + $i]
        load $nodeId 0.0 $nodeLoad
    }
}

puts "顶部施加总载荷: [expr -$totalLoad/1000] kN (压缩)"
puts "每节点载荷: [expr -$nodeLoad/1000] kN"

# ============================================================================
# GPU求解器性能测试
# ============================================================================

puts "\n=========================================="
puts "GPU求解器性能测试"
puts "=========================================="

constraints Plain
numberer Plain
system GPUSolver -debugLevel 1 -enableModule all
test NormDispIncr 1.0e-6 20
algorithm Newton
integrator LoadControl 0.05

analysis Static

puts "\n开始GPU非线性分析 (20步，每步载荷因子0.05)..."
puts "记录时间戳..."

# 记录开始时间
set startTime [clock milliseconds]
set stepTimes [list]

# 逐步施加载荷
set numSteps 20
set ok 0

for {set i 1} {$i <= $numSteps} {incr i} {
    set stepStart [clock milliseconds]

    set ok [analyze 1]

    set stepEnd [clock milliseconds]
    set stepDuration [expr $stepEnd - $stepStart]
    lappend stepTimes $stepDuration

    if {$ok != 0} {
        puts "❌ 分析在第${i}步失败"
        break
    }

    # 输出进度（每5步）
    if {$i % 5 == 0} {
        # 监测中心顶部节点位移
        set centerTopNode [expr $topRowStart + $nx/2]
        set dispY [nodeDisp $centerTopNode 2]
        puts "Step $i/$numSteps - 中心顶部节点位移: [format "%.6e" $dispY] m - 耗时: ${stepDuration} ms"
    }
}

# 记录结束时间
set endTime [clock milliseconds]
set totalTime [expr $endTime - $startTime]

# ============================================================================
# 性能统计
# ============================================================================

puts "\n=========================================="
puts "GPU性能测试结果"
puts "=========================================="
puts "总单元数: $numElements"
puts "总节点数: $numNodes"
puts "分析步数: $numSteps"
puts "总时间: $totalTime ms"

if {$ok == 0} {
    set avgTime [expr $totalTime / double($numSteps)]
    puts "平均时间/步: [format "%.2f" $avgTime] ms"

    # 计算每步时间统计
    set minTime 99999
    set maxTime 0
    foreach t $stepTimes {
        if {$t < $minTime} {set minTime $t}
        if {$t > $maxTime} {set maxTime $t}
    }
    puts "最快步: $minTime ms"
    puts "最慢步: $maxTime ms"

    # 输出关键节点位移
    puts "\n关键节点最终位移:"
    set centerTopNode [expr $topRowStart + $nx/2]
    set leftTopNode $topRowStart
    set rightTopNode [expr $topRowStart + $nx]

    puts "  左上角节点 \[$leftTopNode\]: ([format "%.6e" [nodeDisp $leftTopNode 1]], [format "%.6e" [nodeDisp $leftTopNode 2]]) m"
    puts "  中心顶部节点 \[$centerTopNode\]: ([format "%.6e" [nodeDisp $centerTopNode 1]], [format "%.6e" [nodeDisp $centerTopNode 2]]) m"
    puts "  右上角节点 \[$rightTopNode\]: ([format "%.6e" [nodeDisp $rightTopNode 1]], [format "%.6e" [nodeDisp $rightTopNode 2]]) m"

    puts "\n✓ GPU非线性分析成功完成"
} else {
    puts "\n❌ GPU非线性分析失败"
}

puts "=========================================="

# 保存结果到文件
set outFile [open "gpu_large_performance.txt" w]
puts $outFile "=== GPU大规模非线性性能测试结果 ==="
puts $outFile "网格: ${nx}x${ny} = $numElements 单元"
puts $outFile "材料: PlasticDamageConcrete3d (C30混凝土)"
puts $outFile "分析步数: $numSteps"
puts $outFile "总时间: $totalTime ms"
if {$ok == 0} {
    puts $outFile "平均时间/步: [format "%.2f" [expr $totalTime / double($numSteps)]] ms"
    puts $outFile "成功: 是"
} else {
    puts $outFile "成功: 否"
}
close $outFile

puts "\n结果已保存到: gpu_large_performance.txt"

wipe
